package cn.shop.cloud.web.controller;

import cn.shop.cloud.common.Result;
import cn.shop.cloud.domain.OrderInfo;
import cn.shop.cloud.domain.SeckillOrder;
import cn.shop.cloud.domain.User;
import cn.shop.cloud.redis.MyRedisTemplate;
import cn.shop.cloud.resolver.RedisValue;
import cn.shop.cloud.service.IOrderInfoService;
import cn.shop.cloud.service.ISeckillGoodService;
import cn.shop.cloud.service.ISeckillOrderService;
import cn.shop.cloud.web.mq.MQConstants;
import cn.shop.cloud.web.mq.OrderMessage;
import cn.shop.cloud.web.msg.SeckillCodeMsg;
import cn.shop.cloud.web.redis.SeckillKeyPrefix;
import cn.shop.cloud.web.vo.SeckillGoodVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: untitled1
 * @ClassName OrderInfoController
 * @description:
 * @author: 刘庆东
 * @create: 2024−12-20 09:19
 * @Version 1.0
 **/
@RestController
@RequestMapping("/order")
public class OrderInfoController {

    @Autowired
    private ISeckillGoodService seckillGoodService;

    @Autowired
    private IOrderInfoService orderInfoService;

    @Autowired
    private ISeckillOrderService seckillOrderService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MyRedisTemplate redisTemplate;

    //本地标识
    public static ConcurrentHashMap<Long,Boolean>  isOverSignMap= new ConcurrentHashMap<>();


    //   url: "http://localhost:9000/seckill/order/doSeckill",

    @RequestMapping("/doSeckill")
    public Result<String> doSeckill(Long seckillId,String uuid,@RedisValue User user){

        System.out.println("================-------------"+uuid);

        //1.判断用户是否登录
        if(user==null){
            //没有携带 token登录
            return  Result.error(SeckillCodeMsg.LOGIN_TIMEOUT);//登录信息过期了
        }

        //----- 添加代码
        Boolean isOverSign = isOverSignMap.get(seckillId);
        if(isOverSign!=null && !isOverSign){
            //结束了
            return  Result.error(SeckillCodeMsg.SECKILL_OVER);
        }


        //2.判断参数有没有问题
        if(seckillId==null || seckillId<=0){
            return  Result.error(SeckillCodeMsg.OP_ERROR);
        }

        //3. 根据场次id  查询出对应本场次的秒杀商品
        SeckillGoodVo seckillGoodVo = seckillGoodService.find(seckillId);
        if(seckillGoodVo==null){
            return  Result.error(SeckillCodeMsg.OP_ERROR);
        }

        //4.时间问题  必须是秒杀中
        Date now = new Date();
        if(now.getTime()<seckillGoodVo.getStartDate().getTime() ||
                now.getTime()>seckillGoodVo.getEndDate().getTime()){
            return  Result.error(SeckillCodeMsg.OP_ERROR);
        }
        //5.判断用户是否参与过了本场抢购
        SeckillOrder seckillOrder= seckillOrderService.findUserIdAndSeckillId(user.getId(),seckillId);
        //   18698789339   13
        if(seckillOrder!=null){
            //这个用户已经参与过本场 秒杀活动了
            return Result.error(SeckillCodeMsg.REPEAT_SECKILL);
        }

        //6.判断库存
        if(seckillGoodVo.getStockCount()<=0){
            return Result.error(SeckillCodeMsg.CANCEL_STOCKOVER_ERROR);
        }

        //7.真正的秒杀开始 了
        /*
           7 秒杀动作的原子性   事务中完成 !!!
             7.1秒杀商品表 t_seckill_goods 库存要 -1
             7.2创建商品订单表  t_order_info  [用于后续的支付  发货 ]
             7.3创建秒杀订单 t_seckill_order  用户判断用户是否存在重复抢购

         */

        //三件事在一个方法中实现
        //String orderNo=  orderInfoService.doSeckill(user.getId(),seckillId);

        //我们需要将信息存入redis中
        //库存的扣减
        Long count = redisTemplate.hget(
                SeckillKeyPrefix.SECKILL_STOCK_COUNT, "", seckillId + "", Long.class);

        count--;
        //将数据存入到redis中
        redisTemplate.hset(
                SeckillKeyPrefix.SECKILL_STOCK_COUNT,"",seckillId+"",Long.parseLong(count+""));

        //redis中没有数据的

        if(count<=0){
            //修改标识 商品售罄
            isOverSignMap.put(seckillId,true);
            return Result.error(SeckillCodeMsg.SECKILL_OVER);
        }

        //准备异步下单了
        OrderMessage orderMessage = new OrderMessage(user.getId(),seckillId,uuid);
        //执行异步下单
        rabbitTemplate.convertAndSend(MQConstants.ORDER_PEDDING_QUEUE,orderMessage);
        return Result.success("加入RabbitMQ队列中,请耐心等待....",null);

    }


    //解决redis中数据存储的问题
    @RequestMapping("/initData")
    public Result<String> initData(){
        List<SeckillGoodVo> seckillGoodVoList = seckillGoodService.query();

        for (SeckillGoodVo vo:seckillGoodVoList){
            //存入redis中
            //  存商品
            redisTemplate.hset(
                    SeckillKeyPrefix.SECKILL_GOOD_HASH,"",vo.getId()+"",vo);//先存商品

            //存库存
            redisTemplate.hset(
                    SeckillKeyPrefix.SECKILL_STOCK_COUNT,"",vo.getId()+"",vo.getStockCount());

        }

        return  Result.success("初始化数据到Redis中成功了!!!");

    }



    /*@RequestMapping("/doSeckill")
    public Result<String> doSeckill(Long seckillId,@RedisValue User user){
        //1.判断用户是否登录
        if(user==null){
              //没有携带 token登录
            return  Result.error(SeckillCodeMsg.LOGIN_TIMEOUT);//登录信息过期了
        }

        //2.判断参数有没有问题
        if(seckillId==null || seckillId<=0){
             return  Result.error(SeckillCodeMsg.OP_ERROR);
        }

        //3. 根据场次id  查询出对应本场次的秒杀商品
        SeckillGoodVo seckillGoodVo = seckillGoodService.find(seckillId);
        if(seckillGoodVo==null){
            return  Result.error(SeckillCodeMsg.OP_ERROR);
        }

        //4.时间问题  必须是秒杀中
        Date now = new Date();
        if(now.getTime()<seckillGoodVo.getStartDate().getTime() ||
                now.getTime()>seckillGoodVo.getEndDate().getTime()){
            return  Result.error(SeckillCodeMsg.OP_ERROR);
        }
        //5.判断用户是否参与过了本场抢购
        SeckillOrder seckillOrder= seckillOrderService.findUserIdAndSeckillId(user.getId(),seckillId);
           //   18698789339   13
        if(seckillOrder!=null){
              //这个用户已经参与过本场 秒杀活动了
            return Result.error(SeckillCodeMsg.REPEAT_SECKILL);
        }

        //6.判断库存
        if(seckillGoodVo.getStockCount()<=0){
            return Result.error(SeckillCodeMsg.CANCEL_STOCKOVER_ERROR);
        }

        //7.真正的秒杀开始 了
        *//*
           7 秒杀动作的原子性   事务中完成 !!!
             7.1秒杀商品表 t_seckill_goods 库存要 -1
             7.2创建商品订单表  t_order_info  [用于后续的支付  发货 ]
             7.3创建秒杀订单 t_seckill_order  用户判断用户是否存在重复抢购

         *//*

        //三件事在一个方法中实现
      String orderNo=  orderInfoService.doSeckill(user.getId(),seckillId);

      return Result.success(orderNo);

    }*/

    //      url: "http://localhost:9000/seckill/order/find?orderNo="+orderNo,
    @RequestMapping("/find")
    public Result<OrderInfo> find(String orderNo,@RedisValue User user){
        //判断
        if(StringUtils.isEmpty(orderNo)){
            return  Result.error(SeckillCodeMsg.OP_ERROR);//非法
        }
        if(user==null){
            return  Result.error(SeckillCodeMsg.LOGIN_TIMEOUT);//非法
        }

        //根据订单编号查询订单信息了
        OrderInfo orderInfo=  orderInfoService.find(orderNo);
        //你只能查看自己的订单信息
        if(orderInfo==null|| !orderInfo.getUserId().equals(user.getId())){
            //订单编号存在问题 或者  用户信息和订单所有者不匹配
            return  Result.error(SeckillCodeMsg.OP_ERROR);//非法
        }

        return Result.success(orderInfo);
    }





}
